/***************************************************************************************
 *
 *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 *
 *  By downloading, copying, installing or using the software you agree to this license.
 *  If you do not agree to this license, do not download, install, 
 *  copy or use the software.
 *
 *  Copyright (C) 2014-2019, Happytimesoft Corporation, all rights reserved.
 *
 *  Redistribution and use in binary forms, with or without modification, are permitted.
 *
 *  Unless required by applicable law or agreed to in writing, software distributed 
 *  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
 *  language governing permissions and limitations under the License.
 *
****************************************************************************************/

#include "../bm/sys_inc.h"
#include "rtp.h"
#include "ps.h"


/********************************************************************/

void ps_init_header(PSHDR * ps_h)
{
	if (ps_h == 0)
	{
		return;
	}
	
	ps_h->system_header_start_code[0] = 0x00;
	ps_h->system_header_start_code[1] = 0x00;
	ps_h->system_header_start_code[2] = 0x01;
	ps_h->system_header_start_code[3] = 0xBA;
	ps_h->fix_bit = 0x01;
	ps_h->marker_bit = 0x01;
	ps_h->marker_bit1 = 0x01;
	ps_h->marker_bit2 = 0x01;
	ps_h->marker_bit3 = 0x01;
	ps_h->marker_bit4 = 0x01;
	ps_h->marker_bit5 = 0x01;
	ps_h->reserved = 0x1F;
	ps_h->pack_stuffing_length = 0x00;

	ps_h->system_clock_reference_extension1 = 0;
	ps_h->system_clock_reference_extension2 = 0;

	ps_h->program_mux_rate1 = 0x00;
	ps_h->program_mux_rate2 = 0x5F;
	ps_h->program_mux_rate3 = 0x1A;
}

void ps_init_system_header(PSSYSHDR * sys_h)
{
	if (sys_h == NULL)
	{
		return;
	}
	
	sys_h->system_header_start_code[0] = 0x00;
	sys_h->system_header_start_code[1] = 0x00;
	sys_h->system_header_start_code[2] = 0x01;
	sys_h->system_header_start_code[3] = 0xBB;

	sys_h->header_length[0] = 0x00;
	sys_h->header_length[1] = 0x0C;

	sys_h->rate_bound1 = 0x00;
	sys_h->rate_bound2 = 0xCC;
	sys_h->rate_bound3 = 0x7A;

	sys_h->marker_bit = 0x01;
	sys_h->marker_bit1 = 0x01;

	sys_h->csps_flag = 0x00;
	sys_h->fixed_flag = 0x00;
	sys_h->audio_bound = 0x01;

	sys_h->video_bound = 0x01;
	sys_h->marker_bit2 = 0x01;
	sys_h->video_lock_flag = 0x01;
	sys_h->audio_lock_flag = 0x01;
	sys_h->reserved = 0x7F;

	sys_h->stream_id1 = 0xE0;

	sys_h->std_buffer_size_bound11 = 0x00;
	sys_h->std_buffer_bound_scale1 = 0x01;
	sys_h->marker_bit13 = 0x03;

	sys_h->std_buffer_size_bound12 = 0xE8;

	sys_h->stream_id2 = 0xC0;

	sys_h->std_buffer_size_bound21 = 0x00;
	sys_h->std_buffer_bound_scale2 = 0x00;
	sys_h->marker_bit23 = 0x03;

	sys_h->std_buffer_size_bound22 = 0x20;
}

/*
 * vtype : 0x1B - h264; 0x24 - h265; 0x10 - MPEG-4; 0x80 - SVAC
 * atype : 0x90 - G711; 0X92 - G722.1; 0X93 - G723.1; 0X99 - G729; 0X9B - SVACss
 */
void ps_init_system_map(PSSYSMAP * sys_m, int vtype, int atype)
{
	if (sys_m == NULL)
	{
		return;
	}
	
	sys_m->packet_start_code_prefix[0] = 0x00;
	sys_m->packet_start_code_prefix[1] = 0x00;
	sys_m->packet_start_code_prefix[2] = 0x01;

	sys_m->map_stream_id = 0xBC;
	sys_m->program_stream_map_length[0] = 0x00;
	sys_m->program_stream_map_length[1] = 0x12;

	sys_m->program_stream_map_version = 0x00;
	sys_m->current_next_indicator = 0x01;
	sys_m->reserved1 = 0x03;
	sys_m->program_stream_map_version = 0x01;

	sys_m->reserved2 = 0x7F;
	sys_m->marker_bit = 0x01;

	sys_m->program_stream_info_length[0] = 0x00;
	sys_m->program_stream_info_length[1] = 0x00;

	sys_m->elementary_stream_map_length[0] = 0x00;
	sys_m->elementary_stream_map_length[1] = 0x08;

	sys_m->stream_type1 = vtype; // 0x1B - h264; 0x24 - h265; 0x10 - MPEG-4; 0x80 - SVAC 
	sys_m->elementary_stream_id1 = 0xE0;

	sys_m->elementary_stream_info_length1[0] = 0x00;
	sys_m->elementary_stream_info_length1[1] = 0x00;

	sys_m->stream_type2 = atype; // 0x90 - G711; 0X92 - G722.1; 0X93 - G723.1; 0X99 - G729; 0X9B - SVAC
	sys_m->elementary_stream_id2 = 0xC0;

	sys_m->elementary_stream_info_length2[0] = 0x00;
	sys_m->elementary_stream_info_length2[1] = 0x00;

	sys_m->crc32[0] = 0x00;
	sys_m->crc32[1] = 0x00;
	sys_m->crc32[2] = 0x00;
	sys_m->crc32[3] = 0x00;
}

void ps_init_pes_header(PESHDR * pes_h)
{
	pes_h->packet_start_code_prefix[0] = 0x00;
	pes_h->packet_start_code_prefix[1] = 0x00;
	pes_h->packet_start_code_prefix[2] = 0x01;

	pes_h->PES_packet_length[0] = 0x00;
	pes_h->PES_packet_length[1] = 0x00;

	pes_h->stream_id = 0xE0;

	pes_h->original_or_copy = 0;
	pes_h->copyright = 0;
	pes_h->data_alignment_indicator = 0;
	pes_h->PES_priority = 1;
	pes_h->PES_scrambling_control = 0;
	pes_h->fix_bit = 0x02;

	pes_h->PES_extension_flag = 0;
	pes_h->PES_CRC_flag = 0;
	pes_h->additional_copy_info_flag = 0;
	pes_h->DSM_trick_mode_flag = 0;
	pes_h->ES_rate_flag = 0;
	pes_h->ESCR_flag = 0;
	pes_h->PTS_DTS_flags = 0x02;

	pes_h->PES_header_data_length = 0x05;
}


void ps_init_pts_tag(PPTS_TAG pts_t)
{
	if (pts_t == NULL)
	{
		return;
	}

	pts_t->fix_bit = 0x02;
	pts_t->marker_bit = 0x01;
	pts_t->marker_bit1 = 0x01;
	pts_t->marker_bit2 = 0x01;
}
void ps_set_pts(PPTS_TAG pts_t, uint32 pts)
{
	if (pts_t == NULL)
	{
		return;
	}

	pts_t->PTS1  = (pts >> 30) & 0x07;
	pts_t->PTS21 = (pts >> 22) & 0xFF;
	pts_t->PTS22 = (pts >> 15) & 0x7F;
	pts_t->PTS31 = (pts >> 7) & 0xFF;
	pts_t->PTS32 = pts & 0x7F;
}

/*
 * vtype : 0x1B - h264; 0x24 - h265; 0x10 - MPEG-4; 0x80 - SVAC
 * atype : 0x90 - G711; 0X92 - G722.1; 0X93 - G723.1; 0X99 - G729; 0X9B - SVACss
 */
void ps_init_info(PSPKTI * ps_pkt_i, int vtype, int atype)
{
	if (ps_pkt_i == NULL)
	{
		return;
	}
	
	if (ps_pkt_i->init_flag == 1)
	{
		return;
	}
	
	ps_pkt_i->scr = 0;
	ps_pkt_i->pts = 0;

	ps_init_header(&ps_pkt_i->ePSHeader);
	ps_init_system_header(&ps_pkt_i->ePSSHeader);
	ps_init_system_map(&ps_pkt_i->ePSMHeader, vtype, atype);
	ps_init_pes_header(&ps_pkt_i->ePESHeader);
	ps_init_pts_tag(&ps_pkt_i->ePTS);

	ps_pkt_i->init_flag = 1;
}

int ps_get_pes_size()
{
	return 9;
}

int ps_get_pts_size()
{
	return 5;
}
#if 1
int ps_make_pes_header(PSPKTI * ps_pkt_i, uint8 * header, uint32 framelen, uint32 * pusedlen)
{
	uint32 pes_len = ps_get_pes_size() + ps_get_pts_size() - 6;
	uint16 sDataLen = 0;

	uint32 tatol_len = 65535 - 100;
	if ((pes_len + framelen) > tatol_len)
	{
		sDataLen = tatol_len;
		*pusedlen = tatol_len - pes_len;
	}
	else
	{
		sDataLen = pes_len + framelen;
		*pusedlen = framelen;
	}
	ps_pkt_i->ePESHeader.PES_packet_length[0] = sDataLen >> 8;
	ps_pkt_i->ePESHeader.PES_packet_length[1] = sDataLen & 0xFF;
	//ps_pkt_i->ePESHeader.fix_bit=3;
	ps_pkt_i->ePESHeader.data_alignment_indicator=1;

#if 1
	ps_pkt_i->ePESHeader.PES_header_data_length=0x05;
	ps_pkt_i->ePESHeader.PTS_DTS_flags = 0x02;
	memcpy(header, &ps_pkt_i->ePESHeader, ps_get_pes_size());
	uint8 * buffer=header + ps_get_pes_size();
	int pos =0;
	buffer[pos++] = (ps_pkt_i->pts >> 29 & 0x0e) | 0x21;        //  4 - '0010' 3 - PTS [32..30] 1 - marker_bit
	buffer[pos++] = (ps_pkt_i->pts >> 22);                    //  8 - PTS [29..22]
	buffer[pos++] = (ps_pkt_i->pts >> 14) | 0x01;        //  7 - PTS [21..15]
	buffer[pos++] = (ps_pkt_i->pts >>  7);                    //  8 - PTS [14..7]
	buffer[pos++] = (ps_pkt_i->pts << 1 ) | 0x01;        //  7 - PTS [6..0]
	return ps_get_pes_size() +pos;
#else
	ps_pkt_i->ePESHeader.PES_header_data_length=0x0A;
	ps_pkt_i->ePESHeader.PTS_DTS_flags = 0x03;
	memcpy(header, &ps_pkt_i->ePESHeader, ps_get_pes_size());
	uint8 * buffer=header + ps_get_pes_size();
	int pos =0;
	buffer[pos++] = (ps_pkt_i->pts >> 28 & 0x0e) | 0x31;        //  4 - '0010'
		//  3 - PTS [32..30]
		//  1 - marker_bit
		buffer[pos++] = (ps_pkt_i->pts >> 21);                    //  8 - PTS [29..22]
		buffer[pos++] = (ps_pkt_i->pts >> 13 & 0xfe) | 0x01;        //  7 - PTS [21..15]
		//  1 - marker_bit
		buffer[pos++] = (ps_pkt_i->pts >>  6);                    //  8 - PTS [14..7]
		buffer[pos++] = (ps_pkt_i->pts << 2  & 0xfc) | 0x01;        //  7 - PTS [6..0]
	//--------------------------------------------------------------------------
	buffer[pos++] = (ps_pkt_i->pts >> 28 & 0x0e) | 0x11;        //  4 - '0010'
	buffer[pos++] = (ps_pkt_i->pts >> 21);                    //  8 - PTS [29..22]
	buffer[pos++] = (ps_pkt_i->pts >> 13 & 0xfe) | 0x01;        //  7 - PTS [21..15]
	//  1 - marker_bit
	buffer[pos++] = (ps_pkt_i->pts >>  6);                    //  8 - PTS [14..7]
	buffer[pos++] = (ps_pkt_i->pts << 2  & 0xfc) | 0x01;        //  7 - PTS [6..0]


	return ps_get_pes_size() +pos;
#endif
}
#else


int ps_make_pes_header(PSPKTI * ps_pkt_i, uint8 * header, uint32 framelen, uint32 * pusedlen)
{
	uint32 pes_len = ps_get_pes_size() + ps_get_pts_size() - 6;
	uint16 sDataLen = 0;

	uint32 tatol_len = 65535 - 100;
	if ((pes_len + framelen) > tatol_len)
	{
		sDataLen = tatol_len;
		*pusedlen = tatol_len - pes_len;
	}
	else
	{
		sDataLen = pes_len + framelen;
		*pusedlen = framelen;
	}
	ps_pkt_i->ePESHeader.PES_packet_length[0] = sDataLen >> 8;
	ps_pkt_i->ePESHeader.PES_packet_length[1] = sDataLen & 0xFF;
	memcpy(header, &ps_pkt_i->ePESHeader, ps_get_pes_size());
	ps_set_pts(&ps_pkt_i->ePTS, ps_pkt_i->pts);
	memcpy(header + ps_get_pes_size(), &ps_pkt_i->ePTS, ps_get_pts_size());
	return ps_get_pes_size() + ps_get_pts_size();
}
#endif
int ps_get_header_size()
{
	return 14;
}

void ps_set_system_clock_reference_base(PSHDR * ps_h, uint32 scr)
{
	if (ps_h == NULL)
	{
		return;
	}
	
	ps_h->system_clock_reference_base1 = (scr >> 30) & 0x07;
	ps_h->system_clock_reference_base21 = (scr >> 28) & 0x03;
	ps_h->system_clock_reference_base22 = (scr >> 20) & 0xFF;
	ps_h->system_clock_reference_base23 = (scr >> 15) & 0x1F;
	ps_h->system_clock_reference_base31 = (scr >> 13) & 0x03;
	ps_h->system_clock_reference_base32 = (scr >> 5) & 0xFF;
	ps_h->system_clock_reference_base33 = scr & 0x1F;
}

int ps_make_packet_header(PSPKTI * ps_pkt_i, uint8 *header)
{
	ps_set_system_clock_reference_base(&ps_pkt_i->ePSHeader, ps_pkt_i->scr);

	memcpy(header, &ps_pkt_i->ePSHeader, ps_get_header_size());

	return ps_get_header_size();
}

int ps_get_system_header_size()
{
	return 18;
}

int ps_make_system_header(PSPKTI * ps_pkt_i, uint8 *header)
{
	memcpy(header, &ps_pkt_i->ePSSHeader, ps_get_system_header_size());
	
	return ps_get_system_header_size();
}

int ps_get_system_map_size()
{
	return 24;
}

int ps_make_system_map(PSPKTI * ps_pkt_i, uint8 *header)
{
	memcpy(header, &ps_pkt_i->ePSMHeader, ps_get_system_map_size());

	return ps_get_system_map_size();
}

int ps_make_header(PSPKTI * ps_pkt_i, uint8 * header, uint32 framelen, uint32 ts, int frametype, uint32 * pusedlen)
{
	int offset = 0;
	
	if (ps_pkt_i == NULL)
	{
		return 0;
	}
	
	if (frametype == 1 || frametype == 3) // 1 3 视频帧
	{
		ps_pkt_i->pts = ts;		
		ps_pkt_i->scr = ps_pkt_i->pts;
		
		offset = ps_make_packet_header(ps_pkt_i, header);
		
		// I帧增加系统头和map头
		if (frametype == 3)  
		{
			offset += ps_make_system_header(ps_pkt_i, header + offset);
			offset += ps_make_system_map(ps_pkt_i, header + offset);
		}

		ps_pkt_i->ePESHeader.stream_id = 0xE0;
		
		offset += ps_make_pes_header(ps_pkt_i, header + offset, framelen, pusedlen);
	}
	else if (frametype == 2)	// 2 音频帧
	{
		ps_pkt_i->pts = ts;
		ps_pkt_i->scr = ps_pkt_i->pts;

		offset = ps_make_packet_header(ps_pkt_i, header); //20220925 中粮版本音频 PS头不用PSH
		
		ps_pkt_i->ePESHeader.stream_id = 0xC0;
		
		offset += ps_make_pes_header(ps_pkt_i, header + offset, framelen, pusedlen);
	}
	else if (frametype == 4) // 4 前一个视频包的拆分包
	{
		ps_pkt_i->ePESHeader.stream_id = 0xE0;
		
		offset += ps_make_pes_header(ps_pkt_i, header + offset, framelen, pusedlen);
	}
	else if (frametype == 5) // 5 前一个音频包的拆分包
	{
		ps_pkt_i->ePESHeader.stream_id = 0xC0;
		
		offset = ps_make_pes_header(ps_pkt_i, header + offset, framelen, pusedlen);
	}
	
	return offset;
}





